package com.yzi.core.json
{
	public class JSONDecoder
	{
		private var m_value:*;
		private var m_tokenizer:JSONTokenizer;
		private var m_token:JSONToken;
		
		public function JSONDecoder($string:String)
		{
			m_tokenizer = new JSONTokenizer($string);
			
			nextToken();
			m_value = parseValue();
		}
		
		private function nextToken(): JSONToken	{ return m_token = m_tokenizer.GetNextToken(); }
		
		private function parseArray(): Array
		{
			var result:Array = new Array();
			
			nextToken();
			if(m_token.type != JSONTokenType.RIGHT_BRACKET) {
				while(true)
				{
					result.push(parseValue());
					nextToken();
					
					if(m_token.type == JSONTokenType.RIGHT_BRACKET) {
						break;
					} else if(m_token.type == JSONTokenType.COMMA) {
						nextToken();
					} else {
						m_tokenizer.ParseError("Expecting ] or , but found " + m_token.value);
					}
				}
			}
			
			return result;
		}
		
		private function parseObject(): Object
		{
			var result:Object = new Object();
			var key:String
			
			nextToken();
			if(m_token.type != JSONTokenType.RIGHT_BRACE) {
				while(true)
				{
					if(m_token.type == JSONTokenType.STRING) {
						key = String(m_token.value);
						nextToken();
						
						if(m_token.type == JSONTokenType.COLON) {
							if(m_token.type == JSONTokenType.RIGHT_BRACE) {
								break;
							} else if(m_token.type == JSONTokenType.COMMA) {
								nextToken();
							} else {
								m_tokenizer.ParseError("Expecting ] or , but found " + m_token.value);
							}							
						} else {
							m_tokenizer.ParseError("Expection : but found " + m_token.value);
						}
					} else {
						m_tokenizer.ParseError("Expecting string but found " + m_token.value);
					}
				}
			}
			return result;
		}
		
		private function parseValue(): Object
		{
			if(m_token == null) m_tokenizer.ParseError("Unexpected end od input");
			
			var result:Object;
			
			switch(m_token.type) {
				case JSONTokenType.LEFT_BRACE:
					result = parseObject();
					break;
				case JSONTokenType.LEFT_BRACKET:
					result = parseArray();
					break;
				case JSONTokenType.STRING:
				case JSONTokenType.NUMBER:
				case JSONTokenType.TRUE:
				case JSONTokenType.FALSE:
				case JSONTokenType.NULL:
					result = m_token.value;
					break;
				default:
					m_tokenizer.ParseError("Unexcepted " + m_token.value);
					break;
						
			}
			
			return result;
		}
		
		public function GetValue(): * { return m_value; }
	}
}